# -*- coding: utf-8 -*-
# @Time    : 2020/3/16 12:44
# @Author  : Sunny
# @Site    : 
# @File    : account.py
# @Software: PyCharm
# @WeChat public address : 程序猿与python之间的秘密

import random
from django.db import models
from django.forms import ModelForm
from django.forms import fields
from web import models
from django import forms
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
from django_redis import get_redis_connection
from django.conf import settings
from util.tencent.sms import sms_send_sign
from util.encrypt import md5
from util.bootstrap import BootStrapForm


class UserModelForm(ModelForm):
    phone = fields.CharField(label='手机号',
                             validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误')])
    password = fields.CharField(label='密码', widget=forms.PasswordInput, min_length=8, error_messages={
        'min_length': "密码长度不能小于8个字符",
        'max_length': "密码长度不能大于64个字符"
    }, )
    confirm_password = fields.CharField(label='确认密码', widget=forms.PasswordInput, min_length=8, error_messages={
        'min_length': "密码长度不能小于8个字符",
        'max_length': "密码长度不能大于64个字符"
    }, )
    code = fields.CharField(label='验证码', min_length=4)

    class Meta:
        model = models.User
        fields = ['username', 'email', 'password', 'confirm_password', 'phone', 'code']

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for name, field in self.fields.items():
            field.widget.attrs['class'] = 'form-control'
            field.widget.attrs['placeholder'] = '请输入%s' % (field.label,)

    def clean_username(self):
        user_name = self.cleaned_data.get('username')
        exists = models.User.objects.filter(username=user_name).exists()
        if exists:
            raise ValidationError('用户名存在')
        return user_name

    def clean_email(self):
        email = self.cleaned_data.get('email')
        exists = models.User.objects.filter(email=email).exists()
        if exists:
            raise ValidationError('邮箱已存在')
        return email

    def clean_password(self):
        """
        校验密码
        @return: 
        """
        pwd = self.cleaned_data.get('password')
        return md5(pwd)

    def clean_confirm_password(self):
        password = self.cleaned_data.get('password')
        confirm_pwd = md5(self.cleaned_data.get('confirm_password'))
        if password != confirm_pwd:
            raise ValidationError('两次密码不一致')
        return confirm_pwd

    def clean_phone(self):
        phone = self.cleaned_data.get('phone')
        exists = models.User.objects.filter(phone=phone).exists()
        if exists:
            raise ValidationError('手机号已注册')
        return phone

    def clean_code(self):
        code = self.cleaned_data.get('code')
        phone = self.cleaned_data.get('phone')
        if not phone:
            raise code
        conn = get_redis_connection()
        redis_code = conn.get(phone)
        if not redis_code:
            raise ValidationError('验证码失效或未发送，请重新发送')

        redis_str_code = redis_code.decode('utf-8')

        if code.strip() != redis_str_code:
            raise ValidationError('验证码错误，请重新输入')

        return code


class SendSmsForm(forms.Form):
    phone = forms.CharField(label='手机号', validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'), ])

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_phone(self):
        phone = self.cleaned_data.get('phone')
        tpl = self.request.GET.get('tpl')
        template_id = settings.TENCENT_SMS_TEMPLATE.get(tpl)
        if not template_id:
            raise ValidationError('短信模板不存在')
        phone_exited = models.User.objects.filter(phone=phone)
        if tpl == 'login':  # 登陆
            if not phone_exited:
                raise ValidationError('手机号不存在')
        else:  # 注册
            if phone_exited:
                raise ValidationError('手机号已注册')
        code = random.randrange(1000, 9999)
        res = sms_send_sign(phone, template_id, [code, 1])
        if res['result'] != 0:
            raise ValidationError(f"短信发送失败,{res['errmsg']}")
        conn = get_redis_connection('default')
        conn.set(phone, code, ex=60)

        return phone


class loginSmsForm(BootStrapForm, forms.Form):
    phone = fields.CharField(label='手机号',
                             validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误')])
    code = fields.CharField(label='验证码', min_length=4, widget=forms.TextInput())

    def clean_phone(self):
        phone = self.cleaned_data['phone']
        exists = models.User.objects.filter(phone=phone).exists()
        if not exists:
            raise ValidationError('手机号不存在,未注册')
        return phone

    def clean_code(self):
        code = self.cleaned_data.get('code')
        phone = self.cleaned_data.get('phone')
        # 手机号不存在,未通过校验
        if not phone:
            return code
        conn = get_redis_connection('default')
        redis_code = conn.get(phone)
        if not redis_code:
            raise ValidationError('验证码失效或者未发送,请重新发送')
        redis_str_code = redis_code.decode('utf-8')
        if code.strip() != redis_str_code:
            raise ValidationError('验证码错误,请重新输入')
        return code


class LoginForm(BootStrapForm, forms.Form):
    """
    用户名登陆校验
    """
    username = forms.CharField(label='邮箱或者手机号')
    password = forms.CharField(label='密码', widget=forms.PasswordInput())
    code = forms.CharField(label='图片验证码')

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_password(self):
        pwd = self.cleaned_data['password']

        return md5(pwd)

    def clean_code(self):
        """
        校验图片验证码
        @return:
        """
        code = self.cleaned_data['code']
        # 校验存入session重的code
        session_code = self.request.session.get('image_code')
        if not session_code:
            raise ValidationError('验证码已过期,请重新获取')
        if code.strip().upper() != session_code.strip().upper():
            raise ValidationError('验证码输入错误')
        return code
